package com.yingsheng.bi.hks.repository.dao.service;

import com.yingsheng.bi.hks.repository.dao.mapper.SysSequenceMapper;
import com.yingsheng.bi.hks.repository.dao.po.SysSequence;
import com.yingsheng.bi.hks.template.annotation.SequenceLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
@Transactional(isolation = Isolation.READ_COMMITTED)
public class SequenceDaoService {

    @Autowired
    private SysSequenceMapper sequenceMapper;

    private static final int DEFAULT_STEP = 1;
    private static final Map<String, Long> LOCAL_CACHE = new ConcurrentHashMap<>();

    @SequenceLock("sequence_lock")
    public Long getNextVal(String seqName) {
        return getNextVal(seqName, DEFAULT_STEP);
    }

    public Long getNextVal(String seqName, Integer step) {
        return getNextValWithCache(seqName, step);
    }

    private Long getNextValWithCache(String seqName, Integer step) {
        return LOCAL_CACHE.compute(seqName, (k, v) -> {
            if (v == null || v < System.currentTimeMillis() - 5000) { // 5秒缓存过期
                Long newValue = fetchNextVal(seqName, step);
                return newValue != null ? newValue : v;
            }
            return v;
        });
    }

    private Long fetchNextVal(String seqName, Integer step) {
        while (true) {
            SysSequence entity = sequenceMapper.selectByPrimaryKey(seqName);
            if (entity == null) {
                throw new RuntimeException("序列不存在: " + seqName);
            }

            Long nextVal = entity.getCurrentVal() + step;
            Long maxValue = entity.getMaxVal();

            // 检查最大值限制
            if (maxValue != null && nextVal > maxValue) {
                if (entity.getCycleFlag()) {
                    nextVal = entity.getCurrentVal() + step; // 循环重置
                } else {
                    throw new RuntimeException("序列已达到最大值: " + maxValue);
                }
            }


            SysSequence sequenceForUpdate = new SysSequence();
            sequenceForUpdate.setSeqName(entity.getSeqName());
            sequenceForUpdate.setMaxVal(maxValue);
            sequenceForUpdate.setCurrentVal(nextVal);
            // 原子更新操作
            int updated = sequenceMapper.updateByPrimaryKeySelective(sequenceForUpdate);
            if (updated == 1) {
                return nextVal;
            }
            // 更新失败则重试（乐观锁机制）
        }
    }
}
